package model;

import java.util.Iterator;
import java.util.LinkedList;

import model.interfaces.CompositeNode;
import model.interfaces.Node;
import model.interfaces.Objective;
import model.interfaces.Rule;

public class TreeIterator {

	private Node root = null;
	

	/*Determine the next objective to be achieved*/
	public Node seekNextAchievement(Objective objective, Node actual){
		if(!actual.verify()){
			if(actual.hasChildren())
			{
				CompositeNode nodeAux = (CompositeNode) actual;
				Iterator<Node> it = nodeAux.getChildren().iterator();
				while(it.hasNext()){
					Node son = it.next();
					if(!son.verify())
						return this.seekNextAchievement(objective, son);
				}
			}
			return actual;
		}else{
			if(actual != root){
				LinkedList<Node> siblings = actual.getFather().getChildren();
				Iterator<Node> it = siblings.iterator();
				while(it.hasNext()){
					Node sibling = it.next();
					if(!sibling.verify())
						return this.seekNextAchievement(objective, sibling);
				}
			}
			return null;
		}		
	}

	
	/*Check if the new object added has changed status*/
	public boolean objectChangedStatus(Node actual, Node nextAchievement){
		if(actual == nextAchievement){
			return false;
		}else if(!actual.verify()){
			if(actual.hasChildren()){
				CompositeNode nodeAux = (CompositeNode) actual;
				return this.objectChangedStatus(nodeAux.getChildren().getFirst(), nextAchievement);
			}else
				return true;
		}else{
			if(actual.getFather() != null){
				Iterator<Node> it = actual.getFather().getChildren().iterator();
				while(it.hasNext()){
					boolean resultado = this.objectChangedStatus(it.next(), nextAchievement);
					if(resultado == true)
						return resultado;
				}
			}
			return false;
		}
	}
	
	public void cleanRules(LinkedList<Rule> ruleList, Node nextAchievement){
		for(Rule rule : ruleList){
			boolean clean = ! this.isRuleValid(rule, root, nextAchievement);
			if(clean)
				rule.reset();
		}
	}
	
	public boolean isRuleValid(Rule rule, Node actual, Node nextAchievement){
		if(actual instanceof LeafNode){
			LeafNode leafActual = (LeafNode) actual;
			if(leafActual.getRule() == rule)
				return false;
		}
		if(actual == nextAchievement)
			return true;
		return this.isRuleValid(rule, actual, nextAchievement);
	}


	public void setRoot(Node root) {
		this.root = root;
	}

	
}
